package hunterxhunter.greedisland;

import hunterxhunter.greedisland.data.Ring;
import hunterxhunter.greedisland.data.map.Map;
import hunterxhunter.greedisland.gui.EditorFrame;
import hunterxhunter.greedisland.states.GameplayState;
import hunterxhunter.greedisland.states.MainMenuState;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.SwingUtilities;
import framework.eea.StateBasedGame;
import framework.eea.exception.EEAException;
import framework.eea.gui.JFrameGameContainer;
import hunterxhunter.greedisland.data.map.LayerType;
import hunterxhunter.greedisland.data.map.Tile;
import java.awt.Point;
import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;

/**
 *
 * @author Markus Schr&ouml;der
 */
public class GreedIslandGame extends StateBasedGame {

    public static final String NAME = "Hunter X Hunter - Greed Island";
    private static final Dimension screenSize = new Dimension(512, 512);
    private static final Dimension tileSize = new Dimension(32, 32);
    
    public static final boolean EDIT = true;
    
    private Ring ring;
    private Map map;
    private EditorFrame editor;
    private Point mapID;

    public GreedIslandGame() {
        super(NAME);
        mapID = new Point(0, 0);
    }

    //MAP
    public void loadMap() {
        String ref = "/greedisland/map/" + getMapName();
        URL url = GreedIslandGame.class.getResource(ref);
        if(url == null) {
            System.err.println("can't find map " + ref);
            if(EDIT)
                map = new Map();
            else
                System.exit(1);
        } else {
            try {
                //load map from url
                File mapFile = new File(url.toURI());
                map = Map.loadMap(mapFile);
            } catch (URISyntaxException ex) {
                Logger.getLogger(GreedIslandGame.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
    
    public void saveMap() {
        if(EDIT) {
            //hack
            //File mapFolder = new File("/home/otaku/pjGreedIsland/maven/src/main/resources/greedisland/map");
            File mapFolder = new File("C:\\Users\\Katharina\\Markus\\gitGreedIsland\\maven\\src\\main\\resources\\greedisland\\map");
            File mapFile = new File(mapFolder, getMapName());
            map.save(mapFile);
        }
    }
    
    private String getMapName() {
        return String.format("%02d-%02d.island", mapID.x, mapID.y);
    }
    
    
    //SETTINGS
    @Override
    public void initStatesList(JFrameGameContainer gc) throws EEAException {
        addState(new MainMenuState());
        addState(new GameplayState());
    }

    @Override
    public String[] initImages() {
        return new String[]{
            //MAIN MENU
            "/greedisland/img/joystation.png",
            "/greedisland/img/hunterxhunter.png",
            "/greedisland/img/greedisland.png",
            "/greedisland/img/nen-selection.jpg",
            //gameplay menu
            "/greedisland/img/book-front.jpg",
            "/greedisland/img/book-back.jpg",
            "/greedisland/img/card.png",
            //cards
            "/greedisland/img/card/0079.jpg",
            "/greedisland/img/card/0083.jpg",
            //main characters
            "/greedisland/img/gon.png",
            //map
            "/greedisland/img/map/rpgmaker.png",
            "/greedisland/img/map/entrance.png",
        };
    }

    @Override
    public void initGraphics(final JFrameGameContainer gc) throws EEAException {
        final GreedIslandGame game = this;
        if (EDIT) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    editor = new EditorFrame(game, gc);
                    editor.setLocation(1400 - 750, 200);
                    Dimension size = new Dimension(700, 512);
                    editor.setSize(size);
                    editor.setPreferredSize(size);
                    //editor.setResizable(false);
                    editor.setVisible(true);
                }
            });
            gc.setLocation(new Point(50, 200));
        }

    }

    
    
    //EDITOR
    @Override
    public void mouseClicked(MouseEvent me) {
        if (EDIT && getCurrentStateID() == GameplayState.ID) {
            if (me.getButton() == MouseEvent.BUTTON1) {
                drawTileFromEditor(me.getPoint());
            } else if (me.getButton() == MouseEvent.BUTTON3) {
                Point pos = calculateTileLocation(me.getPoint());
                editor.updateSettings(map.getTile(pos.x, pos.y));
            }
        }
    }

    @Override
    public void mouseDragged(MouseEvent me) {
        if (EDIT && getCurrentStateID() == GameplayState.ID) {
            drawTileFromEditor(me.getPoint());
        }
    }

    private void drawTileFromEditor(Point location) {
        Point pos = calculateTileLocation(location);
        Tile editableTile = map.getTile(pos.x, pos.y, false);
        editableTile.setImageRef(editor.getImageRef(), editor.getLayerType());
        editableTile.setSrc(editor.getSourceRect(), editor.getLayerType());
        editableTile.setCollision(editor.getCollision());
    }

    private Point calculateTileLocation(Point location) {
        GameplayState gps = (GameplayState) getState(GameplayState.ID);
        Point mapOffset = gps.getMapOffset();
        Dimension translation = gps.getTranslation();
        int x = ((location.x - translation.width - mapOffset.x) / 32);
        int y = ((location.y - translation.height - mapOffset.y) / 32);
        return new Point(x, y);
    }

    
    
    // NO USE OF SERVER
    @Override
    public void initServerClient(JFrameGameContainer gc) throws EEAException {
    }

    @Override
    public void deinitServerClient(JFrameGameContainer gc) throws EEAException {
    }

    //GETTER SETTER
    /**
     * @return the ring
     */
    public Ring getRing() {
        return ring;
    }

    /**
     * @param ring the ring to set
     */
    public void setRing(Ring ring) {
        this.ring = ring;
    }

    /**
     * @return the map
     */
    public Map getMap() {
        return map;
    }

    /**
     * @param map the map to set
     */
    public void setMap(Map map) {
        this.map = map;
    }

    public static Dimension getScreenSize() {
        return new Dimension(screenSize);
    }

    public static Dimension getTileSize() {
        return new Dimension(tileSize);
    }

    // MAIN
    public static void main(String[] args) throws IOException, EEAException {
        //HACK
        if(System.getProperty("os.name").startsWith("Linux")) {
            System.err.println("xset r off");
            Runtime.getRuntime().exec(new String[]{"xset", "r", "off"});
            Runtime.getRuntime().addShutdownHook(new Thread() {
                @Override
                public void run() {
                    try {
                        System.err.println("xset r on");
                        Runtime.getRuntime().exec(new String[]{"xset", "r", "on"});
                    } catch (IOException ex) {
                        Logger.getLogger(GreedIslandGame.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            });
        }

        JFrameGameContainer greedIsland = new JFrameGameContainer(new GreedIslandGame(), new Dimension(GreedIslandGame.getScreenSize().width, GreedIslandGame.getScreenSize().height));
        greedIsland.startBlocking();
    }
}
